package com.log4jviewer.ui.preferences.additional;

import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.viewers.ColumnLabelProvider;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Spinner;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.log4jviewer.Activator;

/**
 * Class represents a part of additional preferences page. It is responsible for building a view where log display
 * preferences are placed.
 * 
 * @author <a href="mailto:rd.ryly@gmail.com">Ruslan Diachenko</a>
 */
public class LogDisplayPreferenceView {

    private final Logger logger = LoggerFactory.getLogger(getClass());

    private TableViewer tableViewer;

    // Add widgets to additional preference page.
    public void addChildControls(final Composite composite) {
        createLogImageInsteadOfTextGroup(composite);
        createLogFontGroup(composite);
        createTableViewer(composite);
    }

    private void createTableViewer(final Composite composite) {
        tableViewer = new TableViewer(composite, SWT.SINGLE | SWT.BORDER | SWT.FULL_SELECTION
                | SWT.HIDE_SELECTION);
        tableViewer.setUseHashlookup(true);
        tableViewer.setContentProvider(new LogDisplayContentProvider());

        Table table = tableViewer.getTable();
        table.setHeaderVisible(true);
        table.setLinesVisible(true);
        GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
        table.setLayoutData(gridData);

        createColumns(tableViewer);
        tableViewer.setInput(LogDisplayPreferences.getLogColorSettings());

        int fontSize = LogDisplayPreferences.getLogFontSettings().getFontSize();
        setFontSize(fontSize);
    }

    private void createColumns(final TableViewer tableViewer) {
        // Level name
        final String columnLevelTitle = "Level";
        final int columnLevelSize = 70;
        TableViewerColumn column = createSingleColumn(tableViewer, columnLevelTitle, columnLevelSize);
        column.setLabelProvider(new ColumnLabelProvider() {
            @Override
            public String getText(final Object element) {
                if (LogDisplayPreferences.getLogColorSettings().isLevelImageInsteadOfText()) {
                    return null;
                } else {
                    LogLevelDisplayModel levelDisplayModel = (LogLevelDisplayModel) element;
                    return levelDisplayModel.getLevelName();
                }
            }

            @Override
            public Image getImage(final Object element) {
                if (LogDisplayPreferences.getLogColorSettings().isLevelImageInsteadOfText()) {
                    LogLevelDisplayModel levelDisplayModel = (LogLevelDisplayModel) element;
                    return levelDisplayModel.getImage();
                } else {
                    return null;
                }
            }
        });

        // Log foreground
        final String columnForegroundTitle = "Foreground";
        final int columnForegroundSize = 200;
        column = createSingleColumn(tableViewer, columnForegroundTitle, columnForegroundSize);
        column.setLabelProvider(new ColumnLabelProvider() {
            @Override
            public String getText(final Object element) {
                return "The quick brown fox jumps over the lazy dog";
            }

            @Override
            public Color getForeground(final Object element) {
                LogLevelDisplayModel levelDisplayModel = (LogLevelDisplayModel) element;
                Color color = new Color(Display.getCurrent(), levelDisplayModel.getForeground());
                return color;
            }
        });
        column.setEditingSupport(new LogForegroundCellEditor(tableViewer));

        // Log background
        final String columnBackgroundTitle = "Background";
        final int columnBackgroundSize = 200;
        column = createSingleColumn(tableViewer, columnBackgroundTitle, columnBackgroundSize);
        column.setLabelProvider(new ColumnLabelProvider() {
            @Override
            public String getText(final Object element) {
                return "The quick brown fox jumps over the lazy dog";
            }

            @Override
            public Color getForeground(final Object element) {
                LogLevelDisplayModel levelDisplayModel = (LogLevelDisplayModel) element;
                Color color = new Color(Display.getCurrent(), levelDisplayModel.getForeground());
                return color;
            }

            @Override
            public Color getBackground(final Object element) {
                LogLevelDisplayModel levelDisplayModel = (LogLevelDisplayModel) element;
                Color color = new Color(Display.getCurrent(), levelDisplayModel.getBackground());
                return color;
            }
        });
        column.setEditingSupport(new LogBackgroundCellEditor(tableViewer));
    }

    private TableViewerColumn createSingleColumn(final TableViewer tableViewer, final String columnTitle,
            final int columnWidth) {
        TableViewerColumn viewerColumn = new TableViewerColumn(tableViewer, SWT.NULL);
        TableColumn column = viewerColumn.getColumn();
        column.setText(columnTitle);
        column.setWidth(columnWidth);
        return viewerColumn;
    }

    private void createLogImageInsteadOfTextGroup(final Composite parent) {
        Composite composite = new Composite(parent, SWT.NONE);
        GridLayout gridLayout = new GridLayout();
        gridLayout.numColumns = 2;
        composite.setLayout(gridLayout);

        Label imageOrTextLabel = new Label(composite, SWT.NONE);
        imageOrTextLabel.setText("Use level image in the Level column");

        final Button button = new Button(composite, SWT.CHECK);
        IPreferenceStore store = Activator.getInstance().getPreferenceStore();
        button.setSelection(store.getBoolean(LogDisplayPreferences.getLogColorSettings().getId()));
        button.addSelectionListener(new SelectionListener() {
            @Override
            public void widgetSelected(final SelectionEvent e) {
                boolean isSelected = button.getSelection();
                LogDisplayPreferences.getLogColorSettings().setLevelImageInsteadOfText(isSelected);
                logger.debug("Use log image instead of text: {}", isSelected);
                tableViewer.refresh();
            }

            @Override
            public void widgetDefaultSelected(final SelectionEvent e) {
                // no code
            }
        });
    }

    private void createLogFontGroup(final Composite parent) {
        Composite composite = new Composite(parent, SWT.NONE);
        GridLayout gridLayout = new GridLayout();
        gridLayout.numColumns = 2;
        composite.setLayout(gridLayout);

        Label fontLabel = new Label(composite, SWT.NONE);
        fontLabel.setText("Log's font size");
        final Spinner spinner = new Spinner(composite, SWT.BORDER);
        spinner.setMinimum(0);
        spinner.setMaximum(50);
        spinner.setSelection(LogDisplayPreferences.getLogFontSettings().getFontSize());
        spinner.setIncrement(1);
        spinner.setPageIncrement(5);

        spinner.addModifyListener(new ModifyListener() {
            @Override
            public void modifyText(final ModifyEvent e) {
                logger.debug("Modifying font size value...");
                String newFontSize = spinner.getText();

                if (!newFontSize.isEmpty()) {
                    int size = Integer.parseInt(newFontSize);
                    logger.debug("New font size = {}", size);
                    LogDisplayPreferences.getLogFontSettings().setFontSize(size);
                    setFontSize(size);
                }
            }
        });
    }

    private void setFontSize(final int size) {
        FontData[] fontData = tableViewer.getTable().getFont().getFontData();

        for (int i = 0; i < fontData.length; ++i) {
            fontData[i].setHeight(size);
        }
        final Font newFont = new Font(Display.getCurrent(), fontData);

        for (TableItem item : tableViewer.getTable().getItems()) {
            item.setFont(newFont);
        }
    }

    private class LogDisplayContentProvider implements IStructuredContentProvider {

        @Override
        public void dispose() {
            // no code
        }

        @Override
        public void inputChanged(final Viewer viewer, final Object oldInput, final Object newInput) {
            // no code
        }

        @Override
        public Object[] getElements(final Object inputElement) {
            return ((LogDisplayPreferences.LogColorSettings) inputElement).getLogLevelDisplayModelList();
        }
    }
}